home *** CD-ROM | disk | FTP | other *** search
/ Atari Mega Archive 2 / Atari Mega Archive CD - Volume 2.iso / linux / tools / gtar10.lha / tar.c < prev    next >
C/C++ Source or Header  |  1992-09-09  |  32KB  |  1,346 lines

  1. /* Tar -- a tape archiver.
  2.  
  3.     Copyright (C) 1988 Free Software Foundation
  4.  
  5. GNU tar is distributed in the hope that it will be useful, but WITHOUT ANY
  6. WARRANTY.  No author or distributor accepts responsibility to anyone
  7. for the consequences of using it or for whether it serves any
  8. particular purpose or works at all, unless he says so in writing.
  9. Refer to the GNU tar General Public License for full details.
  10.  
  11. Everyone is granted permission to copy, modify and redistribute GNU tar,
  12. but only under the conditions described in the GNU tar General Public
  13. License.  A copy of this license is supposed to have been given to you
  14. along with GNU tar so you can know your rights and responsibilities.  It
  15. should be in a file named COPYING.  Among other things, the copyright
  16. notice and this notice must be preserved on all copies.
  17.  
  18. In other words, go ahead and share GNU tar, but don't try to stop
  19. anyone else from sharing it farther.  Help stamp out software hoarding!
  20. */
  21.  
  22. /*
  23.  * A tar (tape archiver) program.
  24.  *
  25.  * Written by John Gilmore, ihnp4!hoptoad!gnu, starting 25 Aug 85.
  26.  *
  27.  * @(#)tar.c 1.34 11/6/87 - gnu
  28.  */
  29.  
  30. #include <stdio.h>
  31. #include <sys/types.h>        /* Needed for typedefs in tar.h */
  32. #include <sys/stat.h>        /* JF */
  33. #include "getopt.h"
  34. #include "regex.h"
  35.  
  36. #ifdef USG
  37. #define rindex strrchr
  38. #endif
  39.  
  40. #ifdef BSD42
  41. #include <sys/dir.h>
  42. #else
  43. #ifdef __MSDOS__
  44. #include "msd_dir.h"
  45. #else
  46. #ifdef USG
  47. #ifdef NDIR
  48. #include <ndir.h>
  49. #else
  50. #include <dirent.h>
  51. #endif
  52. #ifndef DIRECT
  53. #define direct dirent
  54. #endif
  55. #define DP_NAMELEN(x) strlen((x)->d_name)
  56. #else
  57. /*
  58.  * FIXME: On other systems there is no standard place for the header file
  59.  * for the portable directory access routines.  Change the #include line
  60.  * below to bring it in from wherever it is.
  61.  */
  62. #include "ndir.h"
  63. #endif
  64. #endif
  65. #endif
  66.  
  67. #ifndef DP_NAMELEN
  68. #define DP_NAMELEN(x)    (x)->d_namlen
  69. #endif
  70.  
  71. #ifndef __STDC__
  72. extern char     *malloc();
  73. extern char     *getenv();
  74. extern char    *strncpy();
  75. extern char    *index();
  76. extern char    *strcpy();    /* JF */
  77. extern char    *strcat();    /* JF */
  78. #endif
  79.  
  80. extern char    *optarg;    /* Pointer to argument */
  81. extern int    optind;        /* Global argv index from getopt */
  82.  
  83. extern char     *ck_malloc();
  84. extern char     *ck_realloc();
  85. /*
  86.  * The following causes "tar.h" to produce definitions of all the
  87.  * global variables, rather than just "extern" declarations of them.
  88.  */
  89. #define TAR_EXTERN /**/
  90. #include "tar.h"
  91.  
  92. /*
  93.  * We should use a conversion routine that does reasonable error
  94.  * checking -- atoi doesn't.  For now, punt.  FIXME.
  95.  */
  96. #define intconv    atoi
  97. extern int    getoldopt();
  98. extern void    read_and();
  99. extern void    list_archive();
  100. extern void    extract_archive();
  101. extern void    diff_archive();
  102. extern void    create_archive();
  103. extern void    update_archive();
  104. extern void    junk_archive();
  105.  
  106. /* JF */
  107. extern time_t    get_date();
  108.  
  109. time_t new_time;
  110.  
  111. static FILE    *namef;        /* File to read names from */
  112. static char    **n_argv;    /* Argv used by name routines */
  113. static int    n_argc;        /* Argc used by name routines */
  114. static char    **n_ind;    /* Store an array of names */
  115. static int    n_indalloc;    /* How big is the array? */
  116. static int    n_indused;    /* How many entries does it have? */
  117. static int    n_indscan;    /* How many of the entries have we scanned? */
  118.  
  119. int f_max_namelen = 0;
  120.  
  121. extern FILE *msg_file;
  122.  
  123. void    describe();
  124. void    options();
  125.  
  126. #ifndef S_IFLNK
  127. #define lstat stat
  128. #endif
  129.  
  130. #ifndef DEFBLOCKING
  131. #define DEFBLOCKING 20
  132. #endif
  133.  
  134. #ifndef DEF_AR_FILE
  135. #define DEF_AR_FILE "tar.out"
  136. #endif
  137.  
  138. /* For long options that unconditionally set a single flag, we have getopt
  139.    do it.  For the others, we share the code for the equivalent short
  140.    named option, the name of which is stored in the otherwise-unused `val'
  141.    field of the `struct option'; for long options that have no equivalent
  142.    short option, we use nongraphic characters as pseudo short option
  143.    characters, starting (for no particular reason) with character 10. */
  144.  
  145. struct option long_options[] =
  146. {
  147.     {"create",        0,    0,            'c'},
  148.     {"append",        0,    0,            'r'},
  149.     {"extract",        0,    0,            'x'},
  150.     {"get",            0,    0,            'x'},
  151.     {"list",        0,    0,            't'},
  152.     {"update",        0,    0,            'u'},
  153.     {"catenate",        0,    0,            'A'},
  154.     {"concatenate",        0,    0,            'A'},
  155.     {"compare",        0,    0,            'd'},
  156.     {"diff",        0,    0,            'd'},
  157.     {"delete",        0,    0,            14},
  158.     {"help",        0,    0,            12},
  159.  
  160.     {"directory",        1,    0,            'C'},
  161.     {"record-number",    0,    &f_sayblock,        1},
  162.     {"files-from",        1,    0,            'T'},
  163.     {"label",        1,    0,            'V'},
  164.     {"exclude-from",    1,    0,            'X'},
  165.     {"exclude",        1,    0,            15},
  166.     {"file",        1,    0,            'f'},
  167.     {"block-size",        1,    0,            'b'},
  168.     {"version",        0,    0,            11},
  169.     {"verbose",         0,    0,            'v'},
  170.     {"totals",        0,    &f_totals,        1},
  171.       
  172.     {"read-full-blocks",    0,    &f_reblock,        1},
  173.     {"starting-file",    1,    0,            'K'},
  174.     {"to-stdout",        0,    &f_exstdout,        1},
  175.     {"ignore-zeros",    0,    &f_ignorez,        1},
  176.     {"keep-old-files",    0,    0,            'k'},
  177.     {"uncompress",        0,    &f_compress,        1},
  178.     {"same-permissions",    0,    &f_use_protection,    1},
  179.     {"preserve-permissions",0,    &f_use_protection,    1},
  180.     {"modification-time",    0,    &f_modified,        1},
  181.     {"preserve",        0,    0,            10},
  182.     {"same-order",        0,    &f_sorted_names,    1},
  183.     {"same-owner",        0,    &f_do_chown,        1},
  184.     {"preserve-order",    0,    &f_sorted_names,    1},
  185.  
  186. #ifdef amigados
  187.     {"amiga-perms",        0,    0,            'a'},
  188. #endif
  189.     {"max-namelen",        1,    0,            'e'},
  190.     {"newer",        1,    0,            'N'},
  191.     {"after-date",        1,    0,            'N'},
  192.     {"newer-mtime",        1,    0,            13},
  193.     {"incremental",        0,    0,            'G'},
  194.     {"listed-incremental",    1,    0,            'g'},
  195.     {"multi-volume",    0,    &f_multivol,        1},
  196.     {"info-script",        1,    &f_run_script_at_end,    1},
  197.     {"absolute-paths",    0,    &f_absolute_paths,    1},
  198.     {"interactive",        0,    &f_confirm,        1},
  199.     {"confirmation",    0,    &f_confirm,        1},
  200.  
  201.     {"verify",        0,    &f_verify,        1},
  202.     {"dereference",        0,    &f_follow_links,    1},
  203.     {"one-file-system",    0,    &f_local_filesys,     1},
  204.     {"old-archive",        0,    0,            'o'},
  205.     {"portability",        0,    0,            'o'},
  206.     {"compress",        0,    &f_compress,        1},
  207.     {"compress-block",    0,    &f_compress,        2},
  208.     {"sparse",        0,    &f_sparse_files,    1},
  209.     {"tape-length",        1,    0,            'L'},
  210.  
  211.     {0, 0, 0, 0}
  212. };
  213.  
  214. /*
  215.  * Main routine for tar.
  216.  */
  217. main(argc, argv)
  218.     int    argc;
  219.     char    **argv;
  220. {
  221.     extern char version_string[];
  222.  
  223.     tar = argv[0];        /* JF: was "tar" Set program name */
  224.     errors = 0;
  225.  
  226.     options(argc, argv);
  227.  
  228.     if(!n_argv)
  229.         name_init(argc, argv);
  230.  
  231.     switch(cmd_mode) {
  232.     case CMD_CAT:
  233.     case CMD_UPDATE:
  234.     case CMD_APPEND:
  235.         update_archive();
  236.         break;
  237.     case CMD_DELETE:
  238.         junk_archive();
  239.         break;
  240.     case CMD_CREATE:
  241.         create_archive();
  242.         if (f_totals)
  243.             fprintf (stderr, "Total bytes written: %d\n", tot_written);
  244.         break;
  245.     case CMD_EXTRACT:
  246.         if (f_volhdr) {
  247.             char *err;
  248.             label_pattern = (struct re_pattern_buffer *)
  249.               ck_malloc (sizeof *label_pattern);
  250.              err = re_compile_pattern (f_volhdr, strlen (f_volhdr),
  251.                           label_pattern);
  252.             if (err) {
  253.                 fprintf (stderr,"Bad regular expression: %s\n",
  254.                      err);
  255.                 errors++;
  256.                 break;
  257.             }
  258.            
  259.         }          
  260.         extr_init();
  261.         read_and(extract_archive);
  262.         break;
  263.     case CMD_LIST:
  264.         if (f_volhdr) {
  265.             char *err;
  266.             label_pattern = (struct re_pattern_buffer *)
  267.               ck_malloc (sizeof *label_pattern);
  268.              err = re_compile_pattern (f_volhdr, strlen (f_volhdr),
  269.                           label_pattern);
  270.             if (err) {
  271.                 fprintf (stderr,"Bad regular expression: %s\n",
  272.                      err);
  273.                 errors++;
  274.                 break;
  275.             }
  276.         }          
  277.         read_and(list_archive);
  278. #if 0
  279.         if (!errors)
  280.             errors = different;
  281. #endif
  282.         break;
  283.     case CMD_DIFF:
  284.         diff_init();
  285.         read_and(diff_archive);
  286.         break;
  287.     case CMD_VERSION:
  288.         fprintf(stderr,"%s\n",version_string);
  289.         break;
  290.     case CMD_NONE:
  291.         msg("you must specify exactly one of the r, c, t, x, or d options\n");
  292.          fprintf(stderr,"For more information, type ``%s +help''.\n",tar);
  293.         exit(EX_ARGSBAD);
  294.     }
  295.     exit(errors);
  296.     /* NOTREACHED */
  297. }
  298.  
  299.  
  300. /*
  301.  * Parse the options for tar.
  302.  */
  303. void
  304. options(argc, argv)
  305.     int    argc;
  306.     char    **argv;
  307. {
  308.     register int    c;        /* Option letter */
  309.     int        ind = -1;
  310.  
  311.     /* Set default option values */
  312.     blocking = DEFBLOCKING;        /* From Makefile */
  313.     ar_file = getenv("TAPE");    /* From environment, or */
  314.     if (ar_file == 0)
  315.         ar_file = DEF_AR_FILE;    /* From Makefile */
  316.  
  317.     /* Parse options */
  318.     while ((c = getoldopt(argc, argv,
  319. #ifndef amigados
  320.                   "-01234567Ab:BcC:de:f:F:g:GhikK:lL:mMN:oOpPrRsStT:uvV:wWxX:zZ",
  321. #else
  322.                   "-01234567aAb:BcC:de:f:F:g:GhikK:lL:mMN:oOpPrRsStT:uvV:wWxX:zZ",
  323. #endif
  324.                   long_options, &ind)) != EOF) {
  325.         switch (c) {
  326.         c